/**
 * 
 */
package com.manthano.util.web.service;

import java.io.PrintWriter;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import com.manthano.util.context.Context;
import com.manthano.util.web.service.bo.ServiceRequest;
import com.manthano.util.web.service.bo.ServiceResponse;

/**
 * @author DELL
 */
public class ServiceFrontController extends AbstractController
{
	private ServiceConfig	serviceConfig	= null;

	/**
	 * @return ServiceConfig
	 */
	public ServiceConfig getServiceConfig()
	{
		return serviceConfig;
	}

	/**
	 * @param serviceConfig
	 */
	public void setServiceConfig(ServiceConfig serviceConfig)
	{
		this.serviceConfig = serviceConfig;
	}

	/*
	 * (non-Javadoc)
	 * @see org.springframework.web.context.support.WebApplicationObjectSupport#
	 * initApplicationContext(org.springframework.context.ApplicationContext)
	 */
	@Override
	protected void initApplicationContext(ApplicationContext context)
	{
		super.initApplicationContext(context);
		Context.addBeanFactory(context);
	}

	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
			throws Exception
	{
		String url = request.getRequestURI().toString();
		String requestType = url.substring(url.lastIndexOf("/") + 1);
		String responseFormatType = request.getParameter("responseFormatType");

		ServiceRequestConverter serviceRequestConverter = serviceConfig.getRequestConverterMap().get(requestType);
		ServiceResponseConverter serviceResponseConverter = serviceConfig.getResoponseConverterMap().get(
				responseFormatType);

		serviceResponseConverter.setResponseHeader(response);
		PrintWriter printWriter = response.getWriter();
		ServiceResponse serviceResponse = new ServiceResponse();

		ServiceRequest serviceRequest = serviceRequestConverter.getServiceRequest(request);

		String method = serviceRequest.getMethod();
		int lastDotIndex = method.lastIndexOf(".");

		if (lastDotIndex == -1)
		{
			serviceResponse.setErrorCode(ServiceResponse.ERR_INVALID_METHOD);
			serviceResponse.setErrorParams(new String[] { method });
			serviceResponse.setError(false);
			return null;
		}

		String moduleName = method.substring(0, lastDotIndex);
		String methodName = method.substring(lastDotIndex + 1);

		ServiceController serviceController = serviceConfig.getControllerMap().get(moduleName);

		String requestMethodType = request.getMethod().toLowerCase();

		int counter = 0;
		boolean typeRequest = true;
		if (requestMethodType.equalsIgnoreCase("post"))
		{
			for (String keyword : serviceConfig.getPostKeywords())
			{
				if (methodName.startsWith(keyword))
				{
					counter++;
					break;
				}
			}
			for (String keyword : serviceConfig.getGetKeywords())
			{
				if (methodName.startsWith(keyword))
				{
					typeRequest = false;
					break;
				}
			}
		}
		else
		{
			for (String keyword : serviceConfig.getGetKeywords())
			{
				if (methodName.startsWith(keyword))
				{
					counter++;
					break;
				}
			}
			for (String keyword : serviceConfig.getPostKeywords())
			{
				if (methodName.startsWith(keyword))
				{
					typeRequest = false;
					break;
				}
			}
		}
		if (counter == 0)
		{
			if (!typeRequest)
			{
				serviceResponse.setErrorCode(ServiceResponse.ERR_INVALID_REQUEST);
			}
			else
			{
				serviceResponse.setErrorCode(ServiceResponse.ERR_INVALID_METHOD);
			}
			serviceResponse.setErrorParams(new String[] { requestMethodType });
			serviceResponse.setError(false);
		}
		try
		{
			Method methodImpl = serviceController.getClass().getMethod(methodName, ServiceRequest.class,
					ServiceResponse.class);
			methodImpl.invoke(serviceController, serviceRequest, serviceResponse);
		}
		catch (NoSuchMethodException e)
		{
			serviceResponse.setErrorCode(ServiceResponse.ERR_METHOD_NOT_FOUND);
			serviceResponse.setErrorParams(new String[] { methodName });
			serviceResponse.setError(false);
		}
		catch (Exception e)
		{
			serviceResponse.setErrorCode(ServiceResponse.ERR_INTERNAL_ERROR);
			serviceResponse.setErrorParams(new String[] { methodName });
			serviceResponse.setError(false);
		}

		printWriter.write(serviceResponseConverter.getResponseString(serviceResponse));
		printWriter.flush();
		printWriter.close();
		return null;
	}
}
